package com.xiaoma.pattern.singleton;

/**
 * https://blog.csdn.net/qq_26222859/article/details/52235930
 * @ClassName LazySingleton
 * @Description 懒汉单例
 * @date 2020-09-22 11:28
 */
public class LazySingleton {

  private static volatile LazySingleton instance = null;

  /**
   * 这个例子在单线程环境可以正常运行，但是在多线程环境就有可能会抛出空指针异常。
   * 为了防止这种情况，我们需要在该方法上使用 synchronized。
   * 这样该方法在多线程环境就是安全的，但是这么做就会导致每次方法调用都需要获取与释放锁，开销很大。
   * 深入分析可以得知只有在初始化的变量的需要真正加锁，一旦初始化之后，直接返回对象即可。
   * @return
   */
  public static LazySingleton getInstance() {
    if (instance == null) {
      instance = new LazySingleton();
    }
    return instance;
  }

  /**
   * 这个方法首先判断变量是否被初始化，没有被初始化，再去获取锁。
   * 获取锁之后，再次判断变量是否被初始化。第二次判断目的在于有可能其他线程获取过锁，已经初始化改变量。
   * 第二次检查还未通过，才会真正初始化变量。
   *
   * 但是new对象，不是一个原子操作，还是存在问题,需要将instance声明为volatile
   * https://www.cnblogs.com/zhuifeng523/p/11360012.html
   * @return
   */
  public  LazySingleton getInstanceSync() {
    if (instance == null) {
      synchronized (this){
        if (instance==null){
        instance = new LazySingleton();
        }
      }
    }
    return instance;
  }





  public static void main(String[] args) {
    LazySingleton.getInstance();
  }

}
